package com.yazdankhah.application;

import com.yazdankhah.beans.Bookmark;
import com.yazdankhah.beans.LeftOff;
import com.yazdankhah.dal.*;
import com.yazdankhah.utils.TextDataTools;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;

/**
 * This is the highest level of Data Access Layer that is specific to this application. All of the
 * methods of this class are specific methods to transparent the database operations from the 
 * rest of this application.
 * 
 * @author ahmad
 */
public class AppDAL {
  
  private static final Logger logger = Logger.getLogger(AppDAL.class);
  
  
  
  public static LeftOff getCurrentLeftOff(long userId) {
    
    String sqlKey = "query.leftOff.by.userId";
    return getBean(sqlKey, LeftOff.class, userId);
    
  } //method
  

  public static boolean deleteLeftOffByUserId(long userId) {
    
    String sqlKey = "delete.leftOff.by.userId";
    return executeUpdate(sqlKey, userId);
  } //method
  
  
  public static boolean deleteBookmarkByUserIdSerial(long userId, short serial) {
    
    String sqlKey = "delete.bookmark.by.userId.serial";
    return executeUpdate(sqlKey, userId, serial);
  } //method
  
  
  public static List<Bookmark> getBookmarks(long userId) {
    
    List<Bookmark> list = new ArrayList<>();
    String sqlKey = "query.bookmark.by.userId";
    
    list = getBeans(sqlKey, Bookmark.class, userId);
    
    return list;
    
  } //method
  
  
  /**
   * A generic method to delete a bean from the database.
   * @param <E> - the type parameter
   * @param bean - the given bean
   * @return true if the deletion is successful and false otherwise
   */
  public static <E> boolean deleteBean(E bean) {
    
    if (bean == null) {
      logger.error("The bean is null! Deletion operation cannot be completed!");
      return false;
    }

    DalSession dSession = DalSession.getDalSession();
    Connection conn = dSession.getDSConnection();
    
    if (conn == null) {
      logger.error("Connection is null! Couldn't get a connection from datasource!");
      return false;
    }
    
    boolean res = SqlUtil.deleteBean(conn, bean);
    if (res) {
      logger.info("The specified record is deleted!");
    }
    
    dSession.closeConnection(conn);
    
    return res;
  } //method
  
  
  
  /**
   * A generic method to insert a bean into the database.
   * @param <E> - the type parameter
   * @param bean - the given bean
   * @return true if the insertion is successful and false otherwise
   */
  public static <E> boolean insertBean(E bean) {
    
    if (bean == null) {
      logger.error("The bean is null! Insertion operation cannot be completed!");
      return false;
    }

    DalSession dSession = DalSession.getDalSession();
    Connection conn = dSession.getDSConnection();
    
    if (conn == null) {
      logger.error("Connection is null! Couldn't get a connection from datasource!");
      return false;
    }
    
    boolean res = SqlUtil.insertBean(conn, bean);
    if (res) {
      logger.info("The specified record is inserted!");
    }
    
    dSession.closeConnection(conn);
    
    return res;
  } //method
  
  
  
  private static <E> List<E> getBeans(String sqlKey, Class<? extends E> c, Object... varArg) {

    String sqlStr = TextDataTools.lookupSql(sqlKey);
    if (sqlStr.isEmpty()) {
      logger.error("The requested SQL string was not found!");
      return null;
    }
    
    DalSession dSession = DalSession.getDalSession();
    Connection conn = dSession.getDSConnection();
    
    if (conn == null) {
      logger.error("Connection is null! Couldn't get a connection from datasource!");
      return null;
    }
    
    List<E> theBeans = (ArrayList<E>) SqlUtil.getBeans(conn, sqlStr, c, varArg);
    
    dSession.closeConnection(conn);
    
    return theBeans;
    
  } //method
  

  private static <E> E getBean(String sqlKey, Class<? extends E> c, Object... varArg) {

    String sqlStr = TextDataTools.lookupSql(sqlKey);
    if (sqlStr.isEmpty()) {
      logger.error("The requested SQL string was not found!");
      return null;
    }
    
    DalSession dSession = DalSession.getDalSession();
    Connection conn = dSession.getDSConnection();
    
    if (conn == null) {
      logger.error("Connection is null! Couldn't get a connection from datasource!");
      return null;
    }
    
    E theBean = (E) SqlUtil.getBean(conn, sqlStr, c, varArg);
    
    dSession.closeConnection(conn);
    
    return theBean;
    
  } //method
  

  private static boolean executeUpdate(String sqlKey, Object... varArg) {
    
    String sqlStr = TextDataTools.lookupSql(sqlKey);
    if (sqlStr.isEmpty()) {
      logger.error("The following SQL string was not found: delete.leftOff.by.userId");
      return false;
    }
    
    DalSession dSession = DalSession.getDalSession();
    Connection conn = dSession.getDSConnection();
    
    if (conn == null) {
      logger.error("Connection is null! Couldn't get a connection from datasource!");
      return false;
    }

    //logger.debug("userId = " + userId);
    int res = SqlUtil.executeUpdate(conn, sqlStr, varArg);
    
    if (res >= 0) {
      logger.info("The specified record is deleted!");
    }
    
    dSession.closeConnection(conn);
    
    return res >= 0;
  } //method
  
} //class
